<!--
@license
Copyright 2024 The Model Explorer Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================
-->

<div class="container"
    [class.graph-info]="showNodeDataProviderSummary"
    [style.font-size.px]="fontSize">
  @for (section of sections; track section.label) {
    @if (section.items.length > 0) {
      <div class="section" #sectionEle
          [class.collapsed]="isSectionCollapsed(section.label)">
        <div class="header" [style.font-size.px]="fontSize - 1">
          <button mat-icon-button class="toggle"
              (click)="handleToggleSection(section.label, sectionEle)">
            <mat-icon>{{getSectionToggleIcon(section.label)}}</mat-icon>
          </button>
          {{getSectionDisplayLabel(section.label)}}
        </div>
        <div class="items-container">
          <table class="metadata-table info-attrs" [style.font-size.px]="fontSize ">
            @for (item of section.items; track item.id || item.label) {
              <tr [class.search-match]="isSearchMatchedAttrId(item.label)">
                <td class="key"><hoverable-label [label]="item.label"></hoverable-label></td>
                <td class="value">
                  @if (item.specialValue) {
                    @switch (item.specialValue.type) {
                      @case (NodeAttributeValueType.NODE_IDS) {
                        @for (nodeId of item.specialValue.nodeIds; track nodeId) {
                          <div class="node-id-attribute"
                              (click)="handleLocateNode(nodeId, $event)">
                            {{nodeId}}
                            <div class="locator-icon-container"
                                [matTooltip]="locatorTooltip"
                                matTooltipClass="multiline-tooltip-left"
                                matTooltipPosition="right">
                              <mat-icon class="locator-icon"
                                  [style.font-size.px]="fontSize"
                                  [style.height.px]="fontSize"
                                  [style.width.px]="fontSize">
                                my_location
                              </mat-icon>
                            </div>
                          </div>
                        }
                      }
                      @case (NodeAttributeValueType.NODE_WITH_ATTRS) {
                         @for (node of item.specialValue.nodes; track node.id) {
                          <div class="node-id-attribute"
                              (click)="handleLocateNode(node.id, $event)">
                            {{node.id}}
                            <div class="locator-icon-container"
                                [matTooltip]="locatorTooltip"
                                matTooltipClass="multiline-tooltip-left"
                                matTooltipPosition="right">
                              <mat-icon class="locator-icon"
                                  [style.font-size.px]="fontSize"
                                  [style.height.px]="fontSize"
                                  [style.width.px]="fontSize">
                                my_location
                              </mat-icon>
                            </div>
                          </div>
                          @for (attr of node.attrs; track attr.key) {
                            <tr>
                              <td class="key">
                                <mat-icon class="bullet">circle</mat-icon>
                                <span class="key-label">{{attr.key}}</span>
                              </td>
                              <td class="value">
                                <hoverable-label [label]="attr.value"></hoverable-label>
                              </td>
                            </tr>
                          }
                        }
                      }
                    }
                  } @else {
                    <expandable-info-text
                        [text]="item.value" [type]="item.label"
                        [bgColor]="item.bgColor || 'transparent'"
                        [textColor]="item.textColor || onSurfaceColor"
                        [initialExpanded]="expandInfoPanelValuesByDefault">
                    </expandable-info-text>
                  }
                </td>
              </tr>
            }
          </table>
        </div>
      </div>
    }
  }

  <!-- Summary for node data provider extensions -->
  <div class="section" *ngIf="showNodeDataProviderSummary" #ndpSectionEle
       [class.collapsed]="isSectionCollapsed(SectionLabel.NODE_DATA_PROVIDERS)">
    <div class="header" [style.font-size.px]="fontSize - 1">
      <button mat-icon-button class="toggle"
          (click)="handleToggleSection(SectionLabel.NODE_DATA_PROVIDERS, ndpSectionEle)">
        <mat-icon>{{getSectionToggleIcon(SectionLabel.NODE_DATA_PROVIDERS)}}</mat-icon>
      </button>
      {{nodeDataProviderPanelTitle}}
    </div>
    <node-data-provider-summary-panel
        [paneId]="paneId"
        [rootGroupNodeId]="curSelectedNodeId">
    </node-data-provider-summary-panel>
  </div>

  <!-- Inputs -->
  <div class="section inputs" *ngIf="inputItems.length > 0" #inputsSectionEle
       [class.collapsed]="isSectionCollapsed(SectionLabel.INPUTS)">
    <div class="header input" [style.font-size.px]="fontSize - 1">
      <div class="header-label-container">
        <button mat-icon-button class="toggle"
            (click)="handleToggleSection(SectionLabel.INPUTS, inputsSectionEle)">
          <mat-icon>{{getSectionToggleIcon(SectionLabel.INPUTS)}}</mat-icon>
        </button>
        inputs ({{curInputsCount}})
      </div>
      @if (showInputPaginator) {
        <paginator [pageSize]="ioPageSize" [itemsCount]="curInputsCount"
            (change)="handleInputPaginatorChanged($event)">
        </paginator>
      }
    </div>
    <ng-container *ngTemplateOutlet="inputItemsTmpl;context:{'items': inputItemsForCurPage}">
    </ng-container>
  </div>

  <!-- Outputs -->
  <div class="section outputs" *ngIf="outputItems.length > 0" #outputsSectionEle
       [class.collapsed]="isSectionCollapsed(SectionLabel.OUTPUTS)">
    <div class="header output" [style.font-size.px]="fontSize - 1">
      <div class="header-label-container">
        <button mat-icon-button class="toggle"
            (click)="handleToggleSection(SectionLabel.OUTPUTS, outputsSectionEle)">
          <mat-icon>{{getSectionToggleIcon(SectionLabel.OUTPUTS)}}</mat-icon>
        </button>
        outputs ({{curOutputsCount}})
      </div>
      @if (showOutputPaginator) {
        <paginator [pageSize]="ioPageSize" [itemsCount]="outputItems.length"
            (change)="handleOutputPaginatorChanged($event)">
        </paginator>
      }
    </div>
    <ng-container *ngTemplateOutlet="outputItemsTmpl;context:{'items': outputItemsForCurPage}">
    </ng-container>
  </div>

  <!-- Identical groups -->
  <div class="section" *ngIf="identicalGroupsData" #identicalGroupsSectionEle
       [class.collapsed]="isSectionCollapsed(SectionLabel.IDENTICAL_GROUPS)">
    <div class="header identical-groups" [style.font-size.px]="fontSize - 1">
      <div class="header-label-container">
        <button mat-icon-button class="toggle"
            (click)="handleToggleSection(SectionLabel.IDENTICAL_GROUPS, identicalGroupsSectionEle)">
          <mat-icon>{{getSectionToggleIcon(SectionLabel.IDENTICAL_GROUPS)}}</mat-icon>
        </button>
        Identical layers ({{identicalGroupNodes.length}})
      </div>
      @if (showIdenticalGroupsPaginator) {
        <paginator [pageSize]="ioPageSize" [itemsCount]="identicalGroupNodes.length"
            (change)="handleIdenticalGroupsPaginatorChanged($event)">
        </paginator>
      }
    </div>
    <io-tree [data]="identicalGroupsData" [rendererId]="curRendererId">
    </io-tree>
  </div>

  <!-- Group inputs -->
  <div class="section inputs" *ngIf="groupInputItems.length > 0" #groupInputsSectionEle
        [class.collapsed]="isSectionCollapsed(SectionLabel.GROUP_INPUTS)">
    <div class="header input" [style.font-size.px]="fontSize - 1">
      <div class="header-label-container">
        <button mat-icon-button class="toggle"
            (click)="handleToggleSection(SectionLabel.GROUP_INPUTS, groupInputsSectionEle)">
          <mat-icon>{{getSectionToggleIcon(SectionLabel.GROUP_INPUTS)}}</mat-icon>
        </button>
        layer inputs ({{curGroupInputsCount}})
      </div>
      @if (showGroupInputPaginator) {
        <paginator [pageSize]="ioPageSize" [itemsCount]="curGroupInputsCount"
            (change)="handleGroupInputPaginatorChanged($event)">
        </paginator>
      }
    </div>
    <ng-container *ngTemplateOutlet="inputItemsTmpl;context:{'items': groupInputItemsForCurPage}">
    </ng-container>
  </div>

  <!-- Group outputs -->
  <div class="section outputs" *ngIf="groupOutputItems.length > 0" #groupOutputsSectionEle
        [class.collapsed]="isSectionCollapsed(SectionLabel.GROUP_OUTPUTS)">
    <div class="header output" [style.font-size.px]="fontSize - 1">
      <div class="header-label-container">
        <button mat-icon-button class="toggle"
            (click)="handleToggleSection(SectionLabel.GROUP_OUTPUTS, groupOutputsSectionEle)">
          <mat-icon>{{getSectionToggleIcon(SectionLabel.GROUP_OUTPUTS)}}</mat-icon>
        </button>
        layer outputs ({{curGroupOutputsCount}})
      </div>
      @if (showGroupOutputPaginator) {
        <paginator [pageSize]="ioPageSize" [itemsCount]="curGroupOutputsCount"
            (change)="handleGroupOutputPaginatorChanged($event)">
        </paginator>
      }
    </div>
    <ng-container *ngTemplateOutlet="outputItemsTmpl;context:{'items': groupOutputItemsForCurPage}">
    </ng-container>
  </div>
</div>

<!-- Resizer -->
<div class="resizer" [class.resizing]="resizing"
    (mousedown)="handleMouseDownResizer($event)">
</div>

<!-- A toggle to hide/show side panel -->
<div class="hide-toggle" [matTooltip]="hideToggleTooltip"
    (click)="toggleHideInfoPanel()">
  <mat-icon>{{hideToggleIconName}}</mat-icon>
</div>

<ng-template #namespaceHierarchy let-value="value">
  <div class="values-count-msg">
    Namespace hierarchy
  </div>
  <div class="namespace-content">
    @for(ns of splitNamespace(value); track $index) {
      <div class="namespace-row">
        {{unEscapeString(ns)}}
      </div>
    }
  </div>
</ng-template>

<ng-template #inputItemsTmpl let-items="items">
  <div class="flat-items-container">
    @for (item of items; track item.opNode.id; let i = $index) {
      <div class="flat-item" [style.font-size.px]="fontSize">
        <div class="name-row"
            [class.search-match]="isSearchMatchedInputValue(getInputTensorTag(item)) || isSearchMatchedInputValue(item.opNode.label)">
          <div class="index">{{item.index}}</div>
          @if (item.opNode.hideInLayout) {
            <div class="name">{{getInputName(item)}}</div>
            @if (item.targetOpNode) {
              <div class="target-op-container">
                <mat-icon class="arrow"
                    [style.font-size.px]="fontSize"
                    [style.height.px]="fontSize"
                    [style.width.px]="fontSize">
                  arrow_forward
                </mat-icon>
                <div class="target-op-node-label">{{item.targetOpNode.label}}</div>
              </div>
            }
          } @else {
            <div class="name locator"
                [attr.data-id]="item.opNode.id"
                (click)="handleLocateNode(item.opNode.id, $event)">
              {{getInputName(item)}}
              <div class="locator-icon-container"
                  [matTooltip]="locatorTooltip"
                  matTooltipClass="multiline-tooltip-left"
                  matTooltipPosition="right">
                <mat-icon class="locator-icon"
                    [style.font-size.px]="fontSize"
                    [style.height.px]="fontSize"
                    [style.width.px]="fontSize">
                  my_location
                </mat-icon>
              </div>
              @if (item.targetOpNode) {
                <div class="target-op-container">
                  <mat-icon class="arrow"
                      [style.font-size.px]="fontSize"
                      [style.height.px]="fontSize"
                      [style.width.px]="fontSize">
                    arrow_forward
                  </mat-icon>
                  <div class="target-op-node-label">{{item.targetOpNode.label}}</div>
                </div>
              }
              <div class="filler"></div>
              @if (!item.opNode.hideInLayout) {
                <div class="visibility-icon-container input"
                    [matTooltip]="getInputOpNodeToggleVisibilityTooltip(item.opNode.id)"
                    matTooltipPosition="left"
                    [class.visible]="getInputOpNodeToggleVisible(item.opNode.id)"
                    (click)="handleToggleInputOpNodeVisibility(item.opNode.id, items, $event)">
                  <mat-icon>
                    {{getInputOpNodeToggleVisibilityIcon(item.opNode.id)}}
                  </mat-icon>
                </div>
              }
            </div>
          }
        </div>
        <table class="metadata-table" [style.font-size.px]="fontSize">
          @for (metadataItem of item.metadataList; track metadataItem.key) {
            @if (getShowMetadata(metadataItem)) {
              <tr #rowEle
                  [class.search-match]="isSearchMatchedInputValue(metadataItem.value)">
                <td class="key">
                  <div class="key-container">
                    <mat-icon class="bullet">circle</mat-icon>
                    <hoverable-label [label]="metadataItem.key"></hoverable-label>
                  </div>
                </td>
                <td class="value">
                  <expandable-info-text
                      [text]="metadataItem.value"
                      [type]="metadataItem.key"
                      [initialExpanded]="expandInfoPanelValuesByDefault">
                  </expandable-info-text>
                </td>
              </tr>
            }
          }
        </table>
      </div>
    }
  </div>
</ng-template>

<ng-template #outputItemsTmpl let-items="items">
  <div class="flat-items-container">
    @for (item of items; track $index; let i = $index; let last = $last) {
      <div class="flat-item">
        <div class="name-row"
            [class.search-match]="isSearchMatchedOutputValue(item.tensorTag)">
          <div class="index">{{item.index}}</div>
          <div class="name">{{getOutputName(item)}}</div>
          @if (item.showSourceOpNode) {
            <div class="source-op-node-label">
              ({{item.sourceOpNode.label}})
            </div>
          }
          <div class="filler"></div>
          @if (getHasConnectedToNodes(item)) {
            <div class="visibility-icon-container output"
                [class.visible]="getOutputToggleVisible(item)"
                [matTooltip]="getOutputToggleVisibilityTooltip(item)"
                matTooltipPosition="left"
                (click)="handleToggleOutputVisibility(item, items, $event)">
              <mat-icon>
                {{getOutputToggleVisibilityIcon(item)}}
              </mat-icon>
            </div>
          }
        </div>
        @if (item.metadataList.length > 0) {
          <table class="metadata-table" [style.font-size.px]="fontSize">
            @for (metadataItem of item.metadataList; track metadataItem.key) {
              <tr [class.search-match]="isSearchMatchedOutputValue(metadataItem.value)">
                <td class="key">
                  <div class="key-container">
                    <mat-icon class="bullet">circle</mat-icon>
                    <hoverable-label [label]="metadataItem.key"></hoverable-label>
                  </div>
                </td>
                <td class="value">
                  @if (metadataItem.key === outputMetadataConnectedTo) {
                    @for (targetNode of metadataItem.connectedNodes; track targetNode.id) {
                      <div class="target-node-container"
                          [attr.data-id]="targetNode.id"
                          [class.search-match]="isSearchMatchedOutputValue(targetNode.label)"
                          [bubble]="namespacePopup"
                          [overlaySize]="constValuesPopupSize"
                          [overlayPositions]="outputConnectsToNamespacePopupPosition"
                          [hoverDelayMs]="50"
                          (click)="handleLocateNode(targetNode.id, $event)">
                        {{targetNode.label}}
                        <div class="locator-icon-container"
                            [matTooltip]="locatorTooltip"
                            matTooltipClass="multiline-tooltip-left"
                            matTooltipPosition="right">
                          <mat-icon class="locator-icon"
                              [style.font-size.px]="fontSize"
                              [style.height.px]="fontSize"
                              [style.width.px]="fontSize">
                            my_location
                          </mat-icon>
                        </div>
                      </div>
                      <ng-template #namespacePopup>
                        <div class="model-explorer-const-values-popup">
                          <ng-container *ngTemplateOutlet="namespaceHierarchy;context:{'value': getNamespaceLabel(targetNode)}">
                          </ng-container>
                        </div>
                      </ng-template>
                    }
                  } @else {
                    <expandable-info-text
                        [text]="metadataItem.value">
                    </expandable-info-text>
                  }
                </td>
              </tr>
            }
          </table>
        }
      </div>
    }
  </div>
</ng-template>
